#include "bootloader.h"
#include "s19file.h"
#include <QThread>
#include <QTimer>

Bootloader::Bootloader(QObject *parent)
    : QObject(parent)
    , m_serial(new QSerialPort(this))
    , m_connected(false)
{
    connect(m_serial, &QSerialPort::readyRead, this, &Bootloader::handleReadyRead);
    connect(m_serial, &QSerialPort::errorOccurred, this, &Bootloader::handleError);
}

Bootloader::~Bootloader()
{
    disconnectSerial();
}

bool Bootloader::connectSerial(const QString &portName, int baudRate)
{
    if (m_connected) {
        disconnectSerial();
    }

    m_serial->setPortName(portName);
    m_serial->setBaudRate(baudRate);
    m_serial->setDataBits(QSerialPort::Data8);
    m_serial->setParity(QSerialPort::NoParity);
    m_serial->setStopBits(QSerialPort::OneStop);
    m_serial->setFlowControl(QSerialPort::NoFlowControl);

    if (m_serial->open(QIODevice::ReadWrite)) {
        m_connected = true;
        emit logMessage(QString("串口连接成功: %1, %2 baud").arg(portName).arg(baudRate));
        return true;
    } else {
        emit errorOccurred(QString("无法打开串口: %1").arg(m_serial->errorString()));
        return false;
    }
}

void Bootloader::disconnectSerial()
{
    if (m_serial->isOpen()) {
        m_serial->close();
    }
    m_connected = false;
    emit logMessage("串口已断开");
}

bool Bootloader::isConnected() const
{
    return m_connected && m_serial->isOpen();
}

void Bootloader::programDevice(const QString &filePath)
{
    if (!isConnected()) {
        emit errorOccurred("串口未连接");
        return;
    }

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        emit errorOccurred(QString("无法打开文件: %1").arg(filePath));
        return;
    }

    emit logMessage("开始编程设备...");

    // 这里实现具体的bootloader协议
    // 这只是一个示例框架
    S19File s19file(filePath.toStdString());
    if (!s19file.LoadFile()) {
        emit logMessage("加载固件失败: 固件有错误!");
        return;
    }
    else {
        emit logMessage("加载固件成功!");
    }


    QByteArray fileData = file.readAll();
    file.close();

    // 模拟编程过程
    int totalSize = fileData.size();
    int chunkSize = 256;
    int chunks = (totalSize + chunkSize - 1) / chunkSize;

    for (int i = 0; i < chunks; i++) {
        if (!isConnected()) {
            emit errorOccurred("编程过程中串口断开");
            return;
        }

        int start = i * chunkSize;
        int end = qMin(start + chunkSize, totalSize);
        QByteArray chunk = fileData.mid(start, end - start);

        // 发送数据块
        if (!sendData(chunk)) {
            emit errorOccurred("发送数据失败");
            return;
        }

        int progress = (i + 1) * 100 / chunks;
        QString message = QString("编程进度: %1/%2 字节").arg(end).arg(totalSize);
        emit progressUpdated(progress, message);

        // 模拟处理时间
        QThread::msleep(10);
    }

    emit operationFinished(true, "编程完成");
    emit logMessage("设备编程成功");
}

void Bootloader::eraseDevice()
{
    if (!isConnected()) {
        emit errorOccurred("串口未连接");
        return;
    }

    emit logMessage("开始擦除设备...");

    // 发送擦除命令
    QByteArray eraseCommand = "ERASE";
    if (sendCommand(eraseCommand)) {
        emit logMessage("擦除命令发送成功");
        // 等待擦除完成
        QThread::msleep(2000); // 模拟擦除时间
        emit operationFinished(true, "擦除完成");
    } else {
        emit errorOccurred("擦除命令发送失败");
    }
}

void Bootloader::resetDevice()
{
    if (!isConnected()) {
        emit errorOccurred("串口未连接");
        return;
    }

    emit logMessage("重置设备...");

    // 发送重置命令
    QByteArray resetCommand = "RESET";
    if (sendCommand(resetCommand)) {
        emit logMessage("重置命令发送成功");
        emit operationFinished(true, "设备已重置");
    } else {
        emit errorOccurred("重置命令发送失败");
    }
}

bool Bootloader::sendCommand(const QByteArray &command)
{
    if (!isConnected()) {
        return false;
    }

    qint64 bytesWritten = m_serial->write(command);
    if (bytesWritten == -1) {
        emit errorOccurred("发送命令失败");
        return false;
    }

    return m_serial->waitForBytesWritten(1000);
}

bool Bootloader::waitForAck(int timeout)
{
    QTimer timer;
    timer.setSingleShot(true);

    QEventLoop loop;
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    connect(m_serial, &QSerialPort::readyRead, &loop, &QEventLoop::quit);

    timer.start(timeout);
    loop.exec();

    if (!timer.isActive()) {
        return false; // 超时
    }

    QByteArray response = m_serial->readAll();
    return response.contains("ACK");
}

bool Bootloader::sendData(const QByteArray &data)
{
    if (!isConnected()) {
        return false;
    }

    qint64 bytesWritten = m_serial->write(data);
    return (bytesWritten != -1) && m_serial->waitForBytesWritten(1000);
}

QByteArray Bootloader::readData(int timeout)
{
    if (!isConnected()) {
        return QByteArray();
    }

    if (m_serial->waitForReadyRead(timeout)) {
        return m_serial->readAll();
    }

    return QByteArray();
}

void Bootloader::handleReadyRead()
{
    QByteArray data = m_serial->readAll();
    m_receiveBuffer.append(data);

    // 处理接收到的数据
    processBootloaderResponse(data);

    emit logMessage(QString("收到数据: %1 字节").arg(data.size()));
}

void Bootloader::handleError(QSerialPort::SerialPortError error)
{
    if (error != QSerialPort::NoError) {
        emit errorOccurred(QString("串口错误: %1").arg(m_serial->errorString()));
        disconnectSerial();
    }
}

void Bootloader::processBootloaderResponse(const QByteArray &response)
{
    // 这里解析bootloader的响应
    // 根据具体的bootloader协议实现

    if (response.contains("ACK")) {
        emit logMessage("收到ACK确认");
    } else if (response.contains("NACK")) {
        emit errorOccurred("收到NACK，操作失败");
    }
}
